package com.qd.panda.stroke;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.ApiResultWrapper;
import com.cdqidi.dto.DelDTO;
import com.cdqidi.exception.ApiException;
import com.cdqidi.repeat.annotation.RepeatSubmit;
import com.cdqidi.util.RedisTemplateUtil;
import com.cdqidi.util.RedissonLockTemplate;
import com.cdqidi.util.page.PageUtil;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.stroke.*;
import com.qd.common.panda.domain.entity.stroke.mystroke.RunMyStrokeVO;
import com.qd.common.sys.annotation.DataScope;
import com.qd.common.sys.domain.login.LoginUser;
import com.qd.common.sys.util.SecurityUtils;
import com.qd.panda.dc.dto.charge.ChargeActionReqDTO;
import com.qd.panda.mq.charge.ChargeConsumerService;
import com.qd.panda.mq.charge.EtcPayService;
import com.qd.panda.service.stroke.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Map;
import java.util.Objects;

/**
 * APP_用户行程
 *
 * @author sjk
 */
@RequiredArgsConstructor
@Validated
@RestController
@RequestMapping("/app/userStroke/")
@Slf4j
public class AppUserStrokeController {
    private final UserStrokeHistoryService userStrokeHistoryService;
    private final UserStrokeService userStrokeService;
    private final UserStrokeHolderService userStrokeHolderService;
    private final UserStrokeConfirmService userStrokeConfirmService;
    private final ChargeConsumerService chargeConsumerService;
    private final RedisTemplateUtil<Object> redisTemplateUtil;

    /**
     * 我的历史行程列表
     *
     * @param dto 查询参数以及页数和每页显示条数
     * @return 列表信息
     */
    @GetMapping(value = "/myUserStrokeHistoryPage")
    public IPage<UserStrokeHistoryDTO> myUserStrokeHistoryPage(UserStrokeHistoryDTO dto) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        dto.setUserId(loginUser.getUserId());
        return userStrokeHistoryService.page(PageUtil.buildPage(dto), dto);
    }

    /**
     * 获取我的历史行程
     *
     * @param id 主键
     * @return 记录
     */
    @GetMapping(value = "/getUserStrokeHistoryById")
    public UserStrokeHistoryDTO getUserStrokeHistoryById(@Validated @NotBlank(message = DelDTO.ID_NULL_MSG) String id) {
        return userStrokeHistoryService.getByIdDto(id);
    }

    /**
     * 当前行程
     *
     * @param userId 用户ID
     * @param parkId 停车场ID
     * @return 当前用户的停车信息
     */
    @GetMapping(value = "/runMyStroke")
    public RunMyStrokeVO runMyStroke(String userId, String parkId) {
        if (!StringUtils.hasLength(userId)) {
            userId = SecurityUtils.getLoginUser().getUserId();
        }
        UserStrokeDTO dto = new UserStrokeDTO();
        dto.setUserId(userId);
        if (StringUtils.hasLength(parkId)) {
            dto.setParkId(parkId);
        }
        dto.setTripStatus(DisplayUtil.TRIP_STATUS_1);

        return userStrokeHolderService.runMyStroke(dto);
    }

    /**
     * 预约
     *
     * @param dto 停车场ID
     * @return 记录
     */
    @RepeatSubmit
    @PostMapping(value = "/reserve")
    public ApiResultWrapper<Object> reserve(@Validated @RequestBody ReserveDTO dto) {
        Integer strongReservation = dto.getStrongReservation();
        if (null == strongReservation) {
            return ApiResult.error("强预约不能为空");
        }
        if (!strongReservation.equals(PandaConstant.STRONG_RESERVATION_1) && !strongReservation.equals(PandaConstant.STRONG_RESERVATION_2)) {
            return ApiResult.error("强预约值错误");
        }
        return userStrokeHolderService.reserve(dto);
    }

    /**
     * 预约支付
     *
     * @param dto 停车场ID
     * @return 记录
     */
    @RepeatSubmit
    @PostMapping(value = "/reservePay")
    public ApiResultWrapper<Object> reservePay(@Validated @RequestBody ReserveDTO dto) {
        return userStrokeHolderService.reservePay(dto);
    }

    /**
     * 取消预约
     *
     * @return 记录
     */
    @RepeatSubmit
    @GetMapping(value = "/cancelReserve")
    public ApiResultWrapper<Object> cancelReserve(@Validated @NotBlank(message = "行程ID不能为空") String sid, String orderId) {
        return userStrokeHolderService.cancelReserve(sid, orderId, DisplayUtil.PROCESS_STATUS_1, false, "用户自主取消");
    }

    /**
     * 用户扫码入场出场
     *
     * @param parkId      停车场ID
     * @param direction   进出方向
     * @param plateNumber 车牌号
     * @param sid         行程ID
     * @return 扫码成功还是失败
     */
    @RepeatSubmit
    @GetMapping(value = "/scanCode")
    public ApiResultWrapper<Object> scanCode(@Validated @NotBlank(message = "停车场ID不能为空") String parkId,
                                             @NotNull(message = "方向不能为空") Integer direction,
                                             @NotBlank(message = "车牌号不能为空") String plateNumber,
                                             @NotBlank(message = "行程ID不能为空") String sid) {
        if (!Objects.equals(direction, PandaConstant.DIRECTION_1)) {
            //&& !Objects.equals(direction, PandaConstant.DIRECTION_2)，现在出场不用扫码
            log.error("方向值错误,direction: {}", direction);
            return ApiResult.error("方向值错误");
        }
        //出场的时候行程ID不能为空(现在改成都不能为空，不预约的订单不能扫码入场)
        return userStrokeHolderService.scanCode(sid, parkId, direction, plateNumber);
    }

    /**
     * 行程确认列表
     *
     * @param dto 查询参数以及页数和每页显示条数
     * @return 列表信息
     */
    @RepeatSubmit
    @GetMapping(value = "/confirmPage")
    @DataScope(orgAlias = "uc", orgIdAlias = "park_id")
    public IPage<UserStrokeConfirmVO> confirmPage(UserStrokeConfirmDTO dto) {
        return userStrokeConfirmService.page(PageUtil.buildPage(dto), dto);
    }

    /**
     * 获取行程确认
     *
     * @param id 主键
     * @return 记录
     */
    @RepeatSubmit
    @GetMapping(value = "/getConfirmById")
    public UserStrokeConfirmDTO getConfirmById(@Validated @NotBlank(message = DelDTO.ID_NULL_MSG) String id) {
        return userStrokeHolderService.getConfirmById(id);
    }


    /**
     * 保安确认
     *
     * @param confirmDTO 确认信息
     * @return 成功 or 失败
     */
    @RepeatSubmit
    @PostMapping(value = "/confirm")
    public ApiResultWrapper<Object> confirm(@Validated @RequestBody ConfirmDTO confirmDTO) {
        return userStrokeHolderService.confirm(confirmDTO);
    }

    /**
     * 创建订单
     *
     * @param map 订单参数
     * @return 支付参数
     */
    @RepeatSubmit
    @PostMapping(value = "/createOrder")
    public ApiResultWrapper<Object> createOrder(@Validated @RequestBody Map<String, Object> map) {
        final String sid = map.get("sid").toString();
        final Object payAmount = map.get("payAmount");
        final Object typeObj = map.get("type");
        final Object orderId = map.get("orderId");
        final Object tripTypeObj = map.get("tripType");
        if (!StringUtils.hasLength(sid)) {
            return ApiResult.error("行程ID不能为空");
        }
        int type;
        try {
            type = Integer.parseInt(typeObj.toString());
        } catch (Exception e) {
            return ApiResult.error("类型值错误");
        }
        if (type < 0 || type > 1) {
            return ApiResult.error("类型值错误");
        }
        Integer tripType = null;
        if(null !=tripTypeObj){
            try {
                tripType = Integer.parseInt(tripTypeObj.toString());
            } catch (Exception e) {
                return ApiResult.error("行程类型值错误");
            }
            final String tripTypeDisplay = DisplayUtil.getTripTypeDisplay(tripType);
            if (!StringUtils.hasLength(tripTypeDisplay)) {
                return ApiResult.error("行程类型值错误");
            }
        }

        final String key = EtcPayService.getPayProcessKey(sid);
        Integer finalTripType = tripType;
        return  RedissonLockTemplate.execute(sid,() -> {
            if (Boolean.TRUE.equals(redisTemplateUtil.getStringRedisTemplate().hasKey(key))) {
                log.error("行程正在支付,当前支付取消,sid: {}", sid);
                return null;
            }
            redisTemplateUtil.set(key, "a");
            try {
                log.info("createOrder-------------------------");
                return userStrokeHolderService.createOrder(sid, payAmount, type, orderId, finalTripType);
            } finally {
                redisTemplateUtil.deleteByKey(key);
            }
        },-1);
    }

    /**
     * 运行中的行程
     *
     * @return 当前用户的停车信息
     */
    @RepeatSubmit
    @GetMapping(value = "/runStrokePage")
    public IPage<UserStrokeDTO> runStrokePage(UserStrokeDTO dto) {
        if (!StringUtils.hasLength(dto.getParkId())) {
            throw new ApiException("停车场ID不能为空");
        }
        return userStrokeService.page(PageUtil.buildPage(dto), dto);
    }

    /**
     * 保安强制关闭行程
     */
    @RepeatSubmit
    @PostMapping(value = "/closeUserStroke")
    public ApiResultWrapper<Object> closeUserStroke(@Validated @RequestBody Map<String, String> map) {
        final String sid = map.get("sid");
        if (!StringUtils.hasLength(sid)) {
            return ApiResult.error("行程ID不能为空");
        }
        userStrokeHolderService.closeUserStroke(sid);
        return ApiResult.success("关闭成功");
    }

    /**
     * 付款结果
     *
     * @param orderId    订单ID
     * @param payStatus  支付状态
     * @param canReserve 是否预约
     */
    @GetMapping(value = "/payResult")
    public ApiResultWrapper<Object> payResult(@Validated @NotBlank(message = "订单ID不能为空") String orderId, Integer payStatus, boolean canReserve) {
        userStrokeHolderService.payResult(orderId, payStatus, canReserve);
        return ApiResult.success("ok");
    }

    /**
     * 取消行程
     */
    @RepeatSubmit
    @GetMapping(value = "/cancelStroke")
    public ApiResultWrapper<Object> cancelStroke(@Validated @NotBlank(message = "行程ID不能为空") String sid) {
        userStrokeHolderService.cancelStroke(sid);
        return ApiResult.success("取消成功");
    }

    /**
     * 充电动作
     * 开始 or停止
     */
    @RepeatSubmit
    @PostMapping(value = "/chargeAction")
    public ApiResultWrapper<Object> chargeAction(@Validated @RequestBody Map<String, String> map) {
        String action = map.get("action");
        String orderId = map.get("orderId");
        if (!StringUtils.hasLength(action)) {
            return ApiResult.error("充电动作不能为空");
        }
        if (!StringUtils.hasLength(orderId)) {
            return ApiResult.error("订单ID不能为空");
        }
        if (action.equals(ChargeActionReqDTO.ACTION_START)) {
            return ApiResult.success(userStrokeHolderService.chargeStartAction(orderId));
        } else if (action.equals(ChargeActionReqDTO.ACTION_STOP)) {
            return ApiResult.success(userStrokeHolderService.chargeStopAction(orderId));
        } else {
            return ApiResult.error("不支持的action");
        }
    }

    /**
     * 新用户创建充电订单
     * 新用户注册以后，查询当前用户的车辆是否处于插枪状态
     * 如果是就生成行程订单，让用户在我的行程里面可以看见
     * 然后用户手动点击开始充电
     */
    @RepeatSubmit
    @PostMapping(value = "/createChargeOrder")
    public ApiResultWrapper<Object> createChargeOrder(@Validated @RequestBody Map<String, String> map) {
        String plateNumber = map.get("plateNumber");
        String parkId = map.get("parkId");
        if (!StringUtils.hasLength(parkId)) {
            return ApiResult.error("停车场ID不能为空");
        }
//        if (!StringUtils.hasLength(plateNumber)) {
//            return ApiResult.error("车牌号不能为空");
//        }
        final String userId = SecurityUtils.getLoginUser().getUserId();
        chargeConsumerService.createChargeOrder(userId, plateNumber, parkId);
        return ApiResult.success();
    }
}